package main

import (
	// 操作系统相关功能
	"os"
	// 信号量相关功能
	"os/signal"
	// 环境（CPU等信息）相关功能
	"runtime"
	// HTTP客户端和服务端相关功能
	"net/http"
	// 日志相关功能
	"log"
	// 时间相关功能
	"time"
	// 命令行参数相关功能
	"flag"
	// 字符串的类型转换
	"strconv"
	// 字符串格式化和屏幕打印
	"fmt"
)
var (
	host					*string
	port					*int
	rootPath             *string
)

func simpleStringHandler(msg string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(msg))
	}
}

// func timeHandler(w http.ResponseWriter, r *http.Request) {
// 	tm := time.Now().Format(time.RFC1123)
// 	w.Write([]byte("The time is: " + tm))
// }
func timeHandler(format string) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		tm := time.Now().Format(format)
		w.Write([]byte("The time is: " + tm))
	}
	return http.HandlerFunc(fn)
}

func router() {
	// 注册/baidu路径作为百度的跳转测试服务
	rh := http.RedirectHandler("http://www.baidu.com", 307)
	http.Handle("/baidu/", rh)

	// 注册/p/路径作为静态文件/页面的展示服务
	fs := http.FileServer(http.Dir(*rootPath))
	http.Handle("/p/", http.StripPrefix("/p/", fs))

	// 注册/tm/路径作为展示当前服务器系统时间的测试服务
	// http.HandleFunc("/tm/", timeHandler)
	th := timeHandler(time.RFC1123)
	http.Handle("/tm/", th);

	http.Handle("/", simpleStringHandler("欢迎使用MiniWeb服务"))
}

func startWebServer() {
	log.Println("======== WebServer Start ========")

	// 注册WEB路由
	router()

	// 装载插件
	loadPlugins()

	// web服务器地址
	var addr = *host + ":" + strconv.Itoa(*port)

	// 暂时这句打印日志的代码只能放到Listen的前面，因为Listen会阻塞线程
	log.Printf("Listening on %s...\n", addr)

	// 监听端口
	err := http.ListenAndServe(addr, nil) //设置监听的端口
	if err != nil {
		log.Printf("ListenAndServe: %v\n", err)
	}

	// 被阻塞了，这句执行不到
	runtime.Goexit()
}

func showPara() {
	fmt.Printf("<监听的IP地址>[%s]\n", *host)
	fmt.Printf("<监听端口号>[%d]\n", *port)
	fmt.Printf("<WEB根目录>[%s]\n", *rootPath)
}

// 返回值：是否需要退出程序
func initPara() bool {
	// flag.String("a *********************************************** common *********************************************** -a", "", "")
	host = flag.String("host", "0.0.0.0", "<监听的IP地址>")
	port = flag.Int("port", 9090, "<监听端口号>")
	rootPath = flag.String("root", ".", "<WEB根目录>")
	var help = flag.Bool("help", false, "<显示帮助信息>")
	flag.Parse()

	if *help == true {
		flag.Usage()
		return true
	}
	showPara()

	return false
}

func main() {
	log.Println("======== App Start ========")

	// 从命令行获取一些基本参数信息
	if initPara() == true {
		return
	}

	// 获得CPU核心数量，设置并发最大数量为CPU核心数
	var num = runtime.NumCPU()
	runtime.GOMAXPROCS(num)

	// 创建一个通信通道，监听终止
    ctrl := make(chan os.Signal, 1)
	signal.Notify(ctrl, os.Interrupt, os.Kill)
	// 开一个新的线程运行startWebServer
	go startWebServer()
	<-ctrl
}
